/********************************************************************************
 *    Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH    *
 *                                                                              *
 *              This software is distributed under the terms of the             *
 *              GNU Lesser General Public Licence (LGPL) version 3,             *
 *                  copied verbatim in the file "LICENSE"                       *
 ********************************************************************************/
#include "HiSmdUnpackTask.h"
#include "HiSmdUnpackedData.h"
#include "HiDaqUnpackUserFunction.h"
#include "HiDaqFormat.h"
#include "HiDaqInfoData.h"

#include "FairRootManager.h"
#include "FairRunAna.h"
#include "FairRuntimeDb.h"

#include <TClonesArray.h>
// ---- Default constructor -------------------------------------------
HiSmdUnpackTask::HiSmdUnpackTask()
    : FairTask("HiSmdUnpackTask")
{
    LOG(debug) << "Default Constructor of HiSmdUnpackTask";
}
// ---- Constructor with parameters (Optional) ---------------------------
HiSmdUnpackTask::HiSmdUnpackTask(HiDaqUnpackTask* BasicUnpacker, Bool_t savetotree)
    : FairTask("HiSmdUnpackTask"),
    fBasicUnpacker(BasicUnpacker),
    fSaveToTree(savetotree)
{
    LOG(debug) << "Constructor with parameters of HiSmdUnpackTask";
}

// ---- Destructor ----------------------------------------------------
HiSmdUnpackTask::~HiSmdUnpackTask() { 
    LOG(debug) << "Destructor of HiSmdUnpackTask"; 
}

// ----  Initialisation  ----------------------------------------------
void HiSmdUnpackTask::SetParContainers()
{
    LOG(debug) << "SetParContainers of HiSmdUnpackTask";
    // Load all necessary parameter containers from the runtime data base
    /*
    FairRunAna* ana = FairRunAna::Instance();
    FairRuntimeDb* rtdb=ana->GetRuntimeDb();
    
    <HiDaqUnpackTaskDataMember> = (<ClassPointer>*)
      (rtdb->getContainer("<ContainerName>"));
    */
}

// ---- Init ----------------------------------------------------------
InitStatus HiSmdUnpackTask::Init()
{
    LOG(debug) << "Initilization of HiSmdUnpackTask";

    // Get a handle from the IO manager
    FairRootManager* ioman = FairRootManager::Instance();
    if(ioman == 0)
    {
        LOG(error) << "FairRootManager not instantiated!";
        return kERROR;
    }

    fInputFile = fBasicUnpacker->GetInputFileStream();

    fDaqInfoArray = static_cast<TClonesArray*>(ioman->GetObject("HiDaqInfoData"));
    if (!fDaqInfoArray) {
        LOG(warn) << "-W- HiSmdUnpackTask::Init: No Data array!";
        return kERROR;
    }

    // Create the TClonesArray for the output data and register
    fUnpackedArray = new TClonesArray("HiSmdUnpackedData");
    ioman->Register("HiSmdUnpackedData", "HiSmdUnpack", fUnpackedArray, kTRUE);

    // Do whatever else is needed at the initilization stage
    // Create histograms to be filled
    // initialize variables

    return kSUCCESS;
}

// ---- ReInit  -------------------------------------------------------
InitStatus HiSmdUnpackTask::ReInit()
{
    LOG(debug) << "Initilization of HiSmdUnpackTask";
    return kSUCCESS;
}

// ---- Exec ----------------------------------------------------------
void HiSmdUnpackTask::Exec(Option_t* /*option*/) { 
    LOG(debug) << "Exec of HiSmdUnpackTask"; 

    // Clear the output array
    fUnpackedArray->Clear();

    // ----循环读取fDaqInfoArray的数据并处理----------------------------------
    for(int i = 0; i < fDaqInfoArray->GetEntriesFast(); i++){
        HiDaqInfoData* DaqInfo = static_cast<HiDaqInfoData*>(fDaqInfoArray->At(i));
        if (!DaqInfo || DaqInfo->fNPxi == 0) continue;
        uint8_t PXI_id = DaqInfo->fPxiID;
        // ---- 判断是否属于该探测器 ------------------------------
        auto iter = PXI_TO_DETECTOR.find(PXI_id);
        if(iter != PXI_TO_DETECTOR.end() && iter->second == DET_SMD){
            fInputFile->seekg(DaqInfo->fFEEAddress, std::ios::beg);
            // ---- 解包数据净荷 ------------------------
            uint32_t Data_processed = 0;
            LOG(info)<<"This is SMD!!";
            while (Data_processed < DaqInfo->fFEELength)
            {
                uint64_t data_word = static_cast<uint64_t>(readLE(fInputFile, 8));
                Data_processed += 8;

                uint16_t channel_id = (data_word >> 52) & 0xFFF;  // 通道ID (12bit)
                uint16_t timeoffset = (data_word >> 40) & 0xFFF; // 时间窗口内偏移 (12bit)
                uint16_t amplitude = (data_word >> 24) & 0xFFFF; // 幅度 (16bit)
                uint32_t position = data_word & 0xFFFFFF; // 位置信息 (24bit)

                new ((*fUnpackedArray)[fUnpackedArray->GetEntriesFast()]) 
                    HiSmdUnpackedData(DaqInfo->fTimeSliceID,
                                    DaqInfo->fPxiID, 
                                    DaqInfo->fFeeID, 
                                    channel_id,
                                    timeoffset,
                                    amplitude,
                                    position
                                    );
            }
        }
    }
}

// ---- Finish --------------------------------------------------------
void HiSmdUnpackTask::Finish() { 
    LOG(debug) << "Finish of HiSmdUnpackTask"; 
}

ClassImp(HiSmdUnpackTask);
